package cn.iocoder.yudao.module.crm.service.module;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.crm.controller.admin.module.vo.module.CrmModulePageReqVO;
import cn.iocoder.yudao.module.crm.controller.admin.module.vo.module.CrmModuleSaveReqVO;
import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDistributeConfigDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmCluePoolConfigDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.cluetransrule.ClueTransRuleDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowStageConfigDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowTypeConfigDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.label.CrmLabelDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.labelset.CrmLabelSetDO;
import cn.iocoder.yudao.module.crm.dal.dataobject.module.CrmModuleDO;
import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueDistributeConfigMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmCluePoolConfigMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.cluetransrule.ClueTransRuleMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerLimitConfigMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerPoolConfigMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.followup.CrmFollowStageConfigMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.followup.CrmFollowTypeConfigMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.label.CrmLabelMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.labelset.CrmLabelSetMapper;
import cn.iocoder.yudao.module.crm.dal.mysql.module.CrmModuleMapper;
import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*;

/**
 * Crm Module Service 实现类
 *
 * @author 数创万维
 */
@Service
@Validated
public class CrmModuleServiceImpl implements CrmModuleService {

    @Resource
    private CrmModuleMapper crmModuleMapper;

    @Resource
    private CrmClueMapper crmClueMapper;

    @Resource
    private CrmCustomerMapper crmCustomerMapper;
    @Resource
    private AdminUserApi adminUserApi;

    @Resource
    private CrmFollowStageConfigMapper followStageConfigMapper;
    @Resource
    private CrmFollowTypeConfigMapper followTypeConfigMapper;

    @Resource
    private CrmCustomerPoolConfigMapper customerPoolConfigMapper;

    @Resource
    private CrmCluePoolConfigMapper cluePoolConfigMapper;

    @Resource
    private CrmCustomerLimitConfigMapper customerLimitConfigMapper;

    @Resource
    private ClueTransRuleMapper clueTransRuleMapper;

    @Resource
    private CrmClueDistributeConfigMapper clueDistributeConfigMapper;

    @Resource
    private CrmLabelSetMapper labelSetMapper;

    @Resource
    private CrmLabelMapper labelMapper;

    @Override
    public Long createModule(CrmModuleSaveReqVO createReqVO) {

        // 检查上限， 最多10个
//        Long count = crmModuleMapper.selectCount();
//        if (count >= 10) {
//            throw exception(MODULE_OVER_LIMIT);
//        }

        // 插入
        CrmModuleDO moduleDO = BeanUtils.toBean(createReqVO, CrmModuleDO.class);
        crmModuleMapper.insert(moduleDO);
        // 返回
        return moduleDO.getId();
    }

    @Override
    public void updateModule(CrmModuleSaveReqVO updateReqVO) {
        // 校验存在
        validateExists(updateReqVO.getId());
        // 更新
        CrmModuleDO updateObj = BeanUtils.toBean(updateReqVO, CrmModuleDO.class);
        crmModuleMapper.updateById(updateObj);
    }

    @Override
    public void deleteModule(Long id) {
        // 校验存在
        validateExists(id);
        // 校验模块下存在线索
        validateModuleHasClue(id);

        // 校验模块下存在客户
        validateModuleHasCustomer(id);

        // 1. 删除跟进阶段
        followStageConfigMapper.delete(CrmFollowStageConfigDO::getModuleId, id);
        // 2. 删除跟进类型
        followTypeConfigMapper.delete(CrmFollowTypeConfigDO::getModuleId, id);
        // 3. 删除客户回收规则
        customerPoolConfigMapper.delete(CrmCustomerPoolConfigDO::getModuleId, id);
        // 4. 删除线索回收规则
        cluePoolConfigMapper.delete(CrmCluePoolConfigDO::getModuleId, id);
        // 5. 删除拥有客户数量限制
        customerLimitConfigMapper.delete(CrmCustomerLimitConfigDO::getModuleId, id);
        // 6. 删除线索转入渠道和分配规则
        clueTransRuleMapper.delete(ClueTransRuleDO::getModuleId, id);
        // 7. 删除线索分配规则
        clueDistributeConfigMapper.delete(CrmClueDistributeConfigDO::getModuleId, id);
        // 8.删除标签分组
        List<CrmLabelSetDO> setList = labelSetMapper.selectList(CrmLabelSetDO::getModuleId, id);
        if (CollUtil.isNotEmpty(setList)) {
            labelSetMapper.delete(CrmLabelSetDO::getModuleId, id);
            labelMapper.delete(new LambdaQueryWrapperX<CrmLabelDO>().in(CrmLabelDO::getSetId, setList.stream().map(CrmLabelSetDO::getId).collect(Collectors.toList())));
        }

        // 删除
        crmModuleMapper.deleteById(id);
    }

    private void validateModuleHasClue(Long id) {
        if (crmClueMapper.selectCount(CrmClueDO::getModuleId, id) > 0) {
            throw exception(MODULE_DELETE_REJECT_HAS_CLUE);
        }
    }

    private void validateModuleHasCustomer(Long id) {
        if (crmCustomerMapper.selectCount(CrmCustomerDO::getModuleId, id) > 0) {
            throw exception(MODULE_DELETE_REJECT_HAS_CUSTOMER);
        }
    }

    private void validateExists(Long id) {
        if (crmModuleMapper.selectById(id) == null) {
            throw exception(MODULE_NOT_EXISTS);
        }
    }

    @Override
    public CrmModuleDO getModule(Long id) {
        return crmModuleMapper.selectById(id);
    }

    @Override
    public PageResult<CrmModuleDO> getModulePage(CrmModulePageReqVO pageReqVO) {
        return crmModuleMapper.selectPage(pageReqVO);
    }

    @Override
    public List<CrmModuleDO> getModuleList(Collection<Long> ids) {
        return crmModuleMapper.selectBatchIds(ids);
    }

    @Override
    public List<CrmModuleDO> getEnableModuleList(Long userId) {

        // 超管可见所有
        if (CrmPermissionUtils.isCrmAdmin()) {
            return crmModuleMapper.selectList();
        }

        AdminUserRespDTO user = adminUserApi.getUser(userId);

        List<CrmModuleDO> allList = crmModuleMapper.selectList(new LambdaQueryWrapperX<CrmModuleDO>()
                .or(w -> w.eq(CrmModuleDO::getType, 0))
                .or(w -> w.like(CrmModuleDO::getDeptIds, StrUtil.concat(true, ",", String.valueOf(user.getDeptId()), ",")))
                .or(w -> w.like(CrmModuleDO::getUserIds, StrUtil.concat(true, ",", String.valueOf(user.getId()), ",")))
        );

        return allList;
    }

    @Override
    public List<CrmModuleDO> getEnableModuleListByTenant(Long tenantId) {
        return TenantUtils.execute(tenantId, () -> crmModuleMapper.selectList());
    }

    @Override
    public CrmModuleDO getEnableModuleListByTenantAndName(Long tenantId, String name) {
        return TenantUtils.execute(tenantId, () -> {
            LambdaQueryWrapper<CrmModuleDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(CrmModuleDO::getName, name);
            queryWrapper.last("limit 1");
            return crmModuleMapper.selectOne(queryWrapper);
        });
    }

    @Override
    public void initModule() {
        //初始化默认模块
        crmModuleMapper.insert(new CrmModuleDO().setName("默认").setType(0).setStatus(1));
    }

}